#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include "Epoll.hpp"
#include "reactor.hpp"
#include "Connection.hpp"

// 关不关心数据是什么？不需要
class Channel : public Connection
{
    static const int buffersize = 1024;

public:
    Channel(int sockfd, InetAddr &addr)
    {
        SetSocketfd(sockfd);
        SetAddr(addr);
        SetEvents(EPOLLIN | EPOLLET);
    }
    // 我们读必须要一次性读完
    void Recver() override
    {
        while (true)
        {

            char buffer[1024];
            int n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0); // 0是非阻塞
            if (n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if (n == 0)
            {
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN) // 因为读完而出错
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 真的出错了
                    std::cout << "读写出错" << std::endl;
                    Excepter();
                    return;
                }
            }
        }
        // 到这里一定收到了报文
        _outbuffer += _cb(_inbuffer);
        Sender();
    }
    void Sender() override
    {
        while (true)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if (n > 0)
            {
                _outbuffer.erase(0, n);
                if (_outbuffer.size() == 0)
                    break;
            }
            else if (n == 0)
            {
                break;
            }
            else if (n < 0)
            {
                if (errno == EAGAIN)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }

        // 1. 发完了
        if (!_outbuffer.empty()) // 2. 缓冲区被写满了！
        {
            // 开启sockfd对写事件的关心！
            Owner()->Eablereadwirte(_sockfd, true, true);
        }
        else
        {
            // 关闭对sockfd写事件的关心
            Owner()->Eablereadwirte(_sockfd, true, false);
        }
    }
    void Excepter() override
    {
    }
};